Refactor metadata generation
authorAlex Crichton <alex@alexcrichton.com>
Mon, 21 Nov 2016 18:05:55 +0000 (10:05 -0800)
committerAlex Crichton <alex@alexcrichton.com>
Mon, 28 Nov 2016 19:19:12 +0000 (11:19 -0800)
Remove generation all the way in manifest-parsing and defer it until we actually
need it during compilation. Additionally remove lots of weird logic that's no
longer necessary that we're hashing quite a few fields.

src/cargo/core/manifest.rs
src/cargo/core/mod.rs
src/cargo/core/package.rs
src/cargo/core/package_id.rs
src/cargo/ops/cargo_clean.rs
src/cargo/ops/cargo_rustc/context.rs
src/cargo/ops/cargo_rustc/fingerprint.rs
src/cargo/ops/cargo_rustc/mod.rs
src/cargo/util/toml.rs

index f5f4217da81da7d8f11ab228d00219a7599531a3..93fac21fdf971ff68122ba5ba4cc9677c9da0d0f 100644 (file)
@@ -6,7 +6,6 @@ use rustc_serialize::{Encoder, Encodable};
 
 use core::{Dependency, PackageId, Summary, SourceId, PackageIdSpec};
 use core::WorkspaceConfig;
-use core::package_id::Metadata;
 
 pub enum EitherManifest {
     Real(Manifest),
@@ -159,7 +158,6 @@ pub struct Target {
     kind: TargetKind,
     name: String,
     src_path: PathBuf,
-    metadata: Option<Metadata>,
     tested: bool,
     benched: bool,
     doc: bool,
@@ -279,7 +277,6 @@ impl Target {
             kind: TargetKind::Bin,
             name: String::new(),
             src_path: PathBuf::new(),
-            metadata: None,
             doc: false,
             doctest: false,
             harness: true,
@@ -289,40 +286,35 @@ impl Target {
         }
     }
 
-    pub fn lib_target(name: &str, crate_targets: Vec<LibKind>,
-                      src_path: &Path,
-                      metadata: Metadata) -> Target {
+    pub fn lib_target(name: &str,
+                      crate_targets: Vec<LibKind>,
+                      src_path: &Path) -> Target {
         Target {
             kind: TargetKind::Lib(crate_targets),
             name: name.to_string(),
             src_path: src_path.to_path_buf(),
-            metadata: Some(metadata),
             doctest: true,
             doc: true,
             ..Target::blank()
         }
     }
 
-    pub fn bin_target(name: &str, src_path: &Path,
-                      metadata: Option<Metadata>) -> Target {
+    pub fn bin_target(name: &str, src_path: &Path) -> Target {
         Target {
             kind: TargetKind::Bin,
             name: name.to_string(),
             src_path: src_path.to_path_buf(),
-            metadata: metadata,
             doc: true,
             ..Target::blank()
         }
     }
 
     /// Builds a `Target` corresponding to the `build = "build.rs"` entry.
-    pub fn custom_build_target(name: &str, src_path: &Path,
-                               metadata: Option<Metadata>) -> Target {
+    pub fn custom_build_target(name: &str, src_path: &Path) -> Target {
         Target {
             kind: TargetKind::CustomBuild,
             name: name.to_string(),
             src_path: src_path.to_path_buf(),
-            metadata: metadata,
             for_host: true,
             benched: false,
             tested: false,
@@ -340,25 +332,21 @@ impl Target {
         }
     }
 
-    pub fn test_target(name: &str, src_path: &Path,
-                       metadata: Metadata) -> Target {
+    pub fn test_target(name: &str, src_path: &Path) -> Target {
         Target {
             kind: TargetKind::Test,
             name: name.to_string(),
             src_path: src_path.to_path_buf(),
-            metadata: Some(metadata),
             benched: false,
             ..Target::blank()
         }
     }
 
-    pub fn bench_target(name: &str, src_path: &Path,
-                        metadata: Metadata) -> Target {
+    pub fn bench_target(name: &str, src_path: &Path) -> Target {
         Target {
             kind: TargetKind::Bench,
             name: name.to_string(),
             src_path: src_path.to_path_buf(),
-            metadata: Some(metadata),
             tested: false,
             ..Target::blank()
         }
@@ -367,7 +355,6 @@ impl Target {
     pub fn name(&self) -> &str { &self.name }
     pub fn crate_name(&self) -> String { self.name.replace("-", "_") }
     pub fn src_path(&self) -> &Path { &self.src_path }
-    pub fn metadata(&self) -> Option<&Metadata> { self.metadata.as_ref() }
     pub fn kind(&self) -> &TargetKind { &self.kind }
     pub fn tested(&self) -> bool { self.tested }
     pub fn harness(&self) -> bool { self.harness }
index 305b6ed7c7404ddb4f93eec1c1a938bc4539033e..e663dcdf27002ab267655133849cb9db7985ba65 100644 (file)
@@ -2,7 +2,7 @@ pub use self::dependency::{Dependency, DependencyInner};
 pub use self::manifest::{Manifest, Target, TargetKind, Profile, LibKind, Profiles};
 pub use self::manifest::{EitherManifest, VirtualManifest};
 pub use self::package::{Package, PackageSet};
-pub use self::package_id::{PackageId, Metadata};
+pub use self::package_id::PackageId;
 pub use self::package_id_spec::PackageIdSpec;
 pub use self::registry::Registry;
 pub use self::resolver::Resolve;
index 03ed7d88729d6f5f72288a1a76b81e80738c269b..11e53cf2c9a0a6f393a35a5df833fc7ca28146d0 100644 (file)
@@ -7,7 +7,7 @@ use std::path::{Path, PathBuf};
 use semver::Version;
 
 use core::{Dependency, Manifest, PackageId, SourceId, Target, TargetKind};
-use core::{Summary, Metadata, SourceMap};
+use core::{Summary, SourceMap};
 use ops;
 use util::{CargoResult, Config, LazyCell, ChainError, internal, human, lev_distance};
 use rustc_serialize::{Encoder,Encodable};
@@ -94,10 +94,6 @@ impl Package {
         self.targets().iter().any(|t| t.is_custom_build())
     }
 
-    pub fn generate_metadata(&self) -> Metadata {
-        self.package_id().generate_metadata()
-    }
-
     pub fn find_closest_target(&self, target: &str, kind: TargetKind) -> Option<&Target> {
         let targets = self.targets();
 
index 8f1992a733e651bfa87925f20aeaa35b744bc1e1..d9224bae1805e616761572f0b576536984a5b0f8 100644 (file)
@@ -9,7 +9,7 @@ use regex::Regex;
 use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};
 use semver;
 
-use util::{CargoResult, CargoError, short_hash, ToSemver};
+use util::{CargoResult, CargoError, ToSemver};
 use core::source::SourceId;
 
 /// Identifier for a specific version of a package in a specific source.
@@ -118,12 +118,6 @@ impl From<PackageIdError> for Box<CargoError> {
     fn from(t: PackageIdError) -> Box<CargoError> { Box::new(t) }
 }
 
-#[derive(PartialEq, Eq, Hash, Clone, RustcEncodable, Debug)]
-pub struct Metadata {
-    pub metadata: String,
-    pub extra_filename: String
-}
-
 impl PackageId {
     pub fn new<T: ToSemver>(name: &str, version: T,
                              sid: &SourceId) -> CargoResult<PackageId> {
@@ -141,13 +135,6 @@ impl PackageId {
     pub fn version(&self) -> &semver::Version { &self.inner.version }
     pub fn source_id(&self) -> &SourceId { &self.inner.source_id }
 
-    pub fn generate_metadata(&self) -> Metadata {
-        let metadata = short_hash(self);
-        let extra_filename = format!("-{}", metadata);
-
-        Metadata { metadata: metadata, extra_filename: extra_filename }
-    }
-
     pub fn with_precise(&self, precise: Option<String>) -> PackageId {
         PackageId {
             inner: Arc::new(PackageIdInner {
@@ -169,14 +156,6 @@ impl PackageId {
     }
 }
 
-impl Metadata {
-    pub fn mix<T: Hash>(&mut self, t: &T) {
-        let new_metadata = short_hash(&(&self.metadata, t));
-        self.extra_filename = format!("-{}", new_metadata);
-        self.metadata = new_metadata;
-    }
-}
-
 impl fmt::Display for PackageId {
     fn fmt(&self, f: &mut Formatter) -> fmt::Result {
         write!(f, "{} v{}", self.inner.name, self.inner.version)?;
index 99b45f7c20a936aed1ce054024e5a2774f2c092d..08f9b78c1d5ec811e87ae8d39b109c66e417b48e 100644 (file)
@@ -73,9 +73,8 @@ pub fn clean(ws: &Workspace, opts: &CleanOptions) -> CargoResult<()> {
     cx.probe_target_info(&units)?;
 
     for unit in units.iter() {
-        let layout = cx.layout(unit);
-        rm_rf(&layout.proxy().fingerprint(&unit.pkg))?;
-        rm_rf(&layout.build(&unit.pkg))?;
+        rm_rf(&cx.layout(unit).proxy().fingerprint(&unit.pkg))?;
+        rm_rf(&cx.layout(unit).build(&unit.pkg))?;
 
         for (src, link_dst, _) in cx.target_filenames(&unit)? {
             rm_rf(&src)?;
index d95b7ee75c6633ba4c8f2b22b387979208e9f30a..0d4dc8aef038863ca53d5cc73295125c25cd972f 100644 (file)
@@ -1,12 +1,15 @@
+#![allow(deprecated)]
+
 use std::collections::{HashSet, HashMap, BTreeSet};
 use std::env;
+use std::fmt;
+use std::hash::{Hasher, Hash, SipHasher};
 use std::path::{Path, PathBuf};
 use std::str::{self, FromStr};
 use std::sync::Arc;
 
-
 use core::{Package, PackageId, PackageSet, Resolve, Target, Profile};
-use core::{TargetKind, Profiles, Metadata, Dependency, Workspace};
+use core::{TargetKind, Profiles, Dependency, Workspace};
 use core::dependency::Kind as DepKind;
 use util::{CargoResult, ChainError, internal, Config, profile, Cfg, human};
 
@@ -53,6 +56,9 @@ struct TargetInfo {
     cfg: Option<Vec<Cfg>>,
 }
 
+#[derive(Clone)]
+pub struct Metadata(u64);
+
 impl<'a, 'cfg> Context<'a, 'cfg> {
     pub fn new(ws: &Workspace<'cfg>,
                resolve: &'a Resolve,
@@ -311,7 +317,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
     /// We build to the path: "{filename}-{target_metadata}"
     /// We use a linking step to link/copy to a predictable filename
     /// like `target/debug/libfoo.{a,so,rlib}` and such.
-    pub fn target_metadata(&self, unit: &Unit) -> Option<Metadata> {
+    pub fn target_metadata(&mut self, unit: &Unit) -> Option<Metadata> {
         // No metadata for dylibs because of a couple issues
         // - OSX encodes the dylib name in the executable
         // - Windows rustc multiple files of which we can't easily link all of them
@@ -336,56 +342,41 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
             return None;
         }
 
-        let metadata = unit.target.metadata().cloned().map(|mut m| {
-            if let Some(features) = self.resolve.features(unit.pkg.package_id()) {
-                let mut feat_vec: Vec<&String> = features.iter().collect();
-                feat_vec.sort();
-                for feat in feat_vec {
-                    m.mix(feat);
-                }
-            }
-            m.mix(unit.profile);
-            m
-        });
-        let mut pkg_metadata = {
-            let mut m = unit.pkg.generate_metadata();
-            if let Some(features) = self.resolve.features(unit.pkg.package_id()) {
+        let mut hasher = SipHasher::new_with_keys(0, 0);
+
+        // Unique metadata per (name, source, version) triple. This'll allow us
+        // to pull crates from anywhere w/o worrying about conflicts
+        unit.pkg.package_id().hash(&mut hasher);
+
+        // Also mix in enabled features to our metadata. This'll ensure that
+        // when changing feature sets each lib is separately cached.
+        match self.resolve.features(unit.pkg.package_id()) {
+            Some(features) => {
                 let mut feat_vec: Vec<&String> = features.iter().collect();
                 feat_vec.sort();
-                for feat in feat_vec {
-                    m.mix(feat);
-                }
+                feat_vec.hash(&mut hasher);
             }
-            m.mix(unit.profile);
-            m
-        };
-
-        if unit.target.is_lib() && unit.profile.test {
-            // Libs and their tests are built in parallel, so we need to make
-            // sure that their metadata is different.
-            metadata.map(|mut m| {
-                m.mix(&"test");
-                m
-            })
-        } else if unit.target.is_bin() && unit.profile.test {
-            // Make sure that the name of this test executable doesn't
-            // conflict with a library that has the same name and is
-            // being tested
-            pkg_metadata.mix(&format!("bin-{}", unit.target.name()));
-            Some(pkg_metadata)
-        } else if unit.pkg.package_id().source_id().is_path() &&
-                  !unit.profile.test {
-            Some(pkg_metadata)
-        } else {
-            metadata
+            None => Vec::<&String>::new().hash(&mut hasher),
         }
+
+        // Throw in the profile we're compiling with. This helps caching
+        // panic=abort and panic=unwind artifacts, additionally with various
+        // settings like debuginfo and whatnot.
+        unit.profile.hash(&mut hasher);
+
+        // Finally throw in the target name/kind. This ensures that concurrent
+        // compiles of targets in the same crate don't collide.
+        unit.target.name().hash(&mut hasher);
+        unit.target.kind().hash(&mut hasher);
+
+        Some(Metadata(hasher.finish()))
     }
 
     /// Returns the file stem for a given target/profile combo (with metadata)
-    pub fn file_stem(&self, unit: &Unit) -> String {
+    pub fn file_stem(&mut self, unit: &Unit) -> String {
         match self.target_metadata(unit) {
-            Some(ref metadata) => format!("{}{}", unit.target.crate_name(),
-                                          metadata.extra_filename),
+            Some(ref metadata) => format!("{}-{}", unit.target.crate_name(),
+                                          metadata),
             None => self.bin_stem(unit),
         }
     }
@@ -407,7 +398,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
 
     /// Returns an Option because in some cases we don't want to link
     /// (eg a dependent lib)
-    pub fn link_stem(&self, unit: &Unit) -> Option<(PathBuf, String)> {
+    pub fn link_stem(&mut self, unit: &Unit) -> Option<(PathBuf, String)> {
         let src_dir = self.out_dir(unit);
         let bin_stem = self.bin_stem(unit);
         let file_stem = self.file_stem(unit);
@@ -441,7 +432,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
     /// filename: filename rustc compiles to. (Often has metadata suffix).
     /// link_dst: Optional file to link/copy the result to (without metadata suffix)
     /// linkable: Whether possible to link against file (eg it's a library)
-    pub fn target_filenames(&self, unit: &Unit)
+    pub fn target_filenames(&mut self, unit: &Unit)
                             -> CargoResult<Vec<(PathBuf, Option<PathBuf>, bool)>> {
         let out_dir = self.out_dir(unit);
         let stem = self.file_stem(unit);
@@ -870,3 +861,9 @@ fn env_args(config: &Config,
 
     Ok(Vec::new())
 }
+
+impl fmt::Display for Metadata {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{:016x}", self.0)
+    }
+}
index 6cc8f88c105a44a9ce4f8746bacc0caf137afad6..952ccac78303f802106477d54aebc9350d66600d 100644 (file)
@@ -531,7 +531,7 @@ pub fn dir(cx: &Context, unit: &Unit) -> PathBuf {
 }
 
 /// Returns the (old, new) location for the dep info file of a target.
-pub fn dep_info_loc(cx: &Context, unit: &Unit) -> PathBuf {
+pub fn dep_info_loc(cx: &mut Context, unit: &Unit) -> PathBuf {
     dir(cx, unit).join(&format!("dep-{}", filename(cx, unit)))
 }
 
@@ -653,7 +653,7 @@ fn mtime_if_fresh<I>(output: &Path, paths: I) -> Option<FileTime>
     }
 }
 
-fn filename(cx: &Context, unit: &Unit) -> String {
+fn filename(cx: &mut Context, unit: &Unit) -> String {
     // file_stem includes metadata hash. Thus we have a different
     // fingerprint for every metadata hash version. This works because
     // even if the package is fresh, we'll still link the fresh target
index 02e1088303b9bb297f3356b1b513568724a70dd9..73f3fed96a589a7b05cb1ebde36a7e47bd95d9a0 100644 (file)
@@ -421,7 +421,7 @@ fn add_plugin_deps(rustc: &mut ProcessBuilder,
     Ok(())
 }
 
-fn prepare_rustc(cx: &Context,
+fn prepare_rustc(cx: &mut Context,
                  crate_types: Vec<&str>,
                  unit: &Unit) -> CargoResult<ProcessBuilder> {
     let mut base = cx.compilation.rustc_process(unit.pkg)?;
@@ -509,7 +509,7 @@ fn root_path(cx: &Context, unit: &Unit) -> PathBuf {
     }
 }
 
-fn build_base_args(cx: &Context,
+fn build_base_args(cx: &mut Context,
                    cmd: &mut ProcessBuilder,
                    unit: &Unit,
                    crate_types: &[&str]) {
@@ -610,8 +610,8 @@ fn build_base_args(cx: &Context,
 
     match cx.target_metadata(unit) {
         Some(m) => {
-            cmd.arg("-C").arg(&format!("metadata={}", m.metadata));
-            cmd.arg("-C").arg(&format!("extra-filename={}", m.extra_filename));
+            cmd.arg("-C").arg(&format!("metadata={}", m));
+            cmd.arg("-C").arg(&format!("extra-filename=-{}", m));
         }
         None => {
             cmd.arg("-C").arg(&format!("metadata={}", short_hash(unit.pkg)));
@@ -645,17 +645,16 @@ fn build_plugin_args(cmd: &mut ProcessBuilder, cx: &Context, unit: &Unit) {
     opt(cmd, "-C", "linker=", cx.linker(unit.kind).map(|s| s.as_ref()));
 }
 
-fn build_deps_args(cmd: &mut ProcessBuilder, cx: &Context, unit: &Unit)
+fn build_deps_args(cmd: &mut ProcessBuilder, cx: &mut Context, unit: &Unit)
                    -> CargoResult<()> {
-    let layout = cx.layout(unit);
     cmd.arg("-L").arg(&{
         let mut deps = OsString::from("dependency=");
-        deps.push(layout.deps());
+        deps.push(cx.layout(unit).deps());
         deps
     });
 
     if unit.pkg.has_custom_build() {
-        cmd.env("OUT_DIR", &layout.build_out(unit.pkg));
+        cmd.env("OUT_DIR", &cx.layout(unit).build_out(unit.pkg));
     }
 
     for unit in cx.dep_targets(unit)?.iter() {
@@ -666,7 +665,7 @@ fn build_deps_args(cmd: &mut ProcessBuilder, cx: &Context, unit: &Unit)
 
     return Ok(());
 
-    fn link_to(cmd: &mut ProcessBuilder, cx: &Context, unit: &Unit)
+    fn link_to(cmd: &mut ProcessBuilder, cx: &mut Context, unit: &Unit)
                -> CargoResult<()> {
         for (dst, _link_dst, linkable) in cx.target_filenames(unit)? {
             if !linkable {
index c5d70b7098bd7dc2f4682896a4287ab602331117..5e5dc93a669e86033d2afd05919b73fe72269bfe 100644 (file)
@@ -14,7 +14,6 @@ use core::{Summary, Manifest, Target, Dependency, DependencyInner, PackageId};
 use core::{EitherManifest, VirtualManifest};
 use core::dependency::{Kind, Platform};
 use core::manifest::{LibKind, Profile, ManifestMetadata};
-use core::package_id::Metadata;
 use sources::CRATES_IO;
 use util::{self, CargoResult, human, ToUrl, ToSemver, ChainError, Config};
 
@@ -437,7 +436,6 @@ impl TomlManifest {
         }
 
         let pkgid = project.to_package_id(source_id)?;
-        let metadata = pkgid.generate_metadata();
 
         // If we have no lib at all, use the inferred lib if available
         // If we have a lib with a path, we're done
@@ -550,8 +548,7 @@ impl TomlManifest {
                                 new_build,
                                 &examples,
                                 &tests,
-                                &benches,
-                                &metadata);
+                                &benches);
 
         if targets.is_empty() {
             debug!("manifest has no build targets");
@@ -1064,8 +1061,7 @@ fn normalize(lib: &Option<TomlLibTarget>,
              custom_build: Option<PathBuf>,
              examples: &[TomlExampleTarget],
              tests: &[TomlTestTarget],
-             benches: &[TomlBenchTarget],
-             metadata: &Metadata) -> Vec<Target> {
+             benches: &[TomlBenchTarget]) -> Vec<Target> {
     fn configure(toml: &TomlTarget, target: &mut Target) {
         let t2 = target.clone();
         target.set_tested(toml.test.unwrap_or(t2.tested()))
@@ -1080,9 +1076,7 @@ fn normalize(lib: &Option<TomlLibTarget>,
               });
     }
 
-    fn lib_target(dst: &mut Vec<Target>,
-                  l: &TomlLibTarget,
-                  metadata: &Metadata) {
+    fn lib_target(dst: &mut Vec<Target>, l: &TomlLibTarget) {
         let path = l.path.clone().unwrap_or(
             PathValue::Path(Path::new("src").join(&format!("{}.rs", l.name())))
         );
@@ -1095,14 +1089,8 @@ fn normalize(lib: &Option<TomlLibTarget>,
             }
         };
 
-        // Binaries, examples, etc, may link to this library. Their crate names
-        // have a high likelihood to being the same as ours, however, so we need
-        // some extra metadata in our name to ensure symbols won't collide.
-        let mut metadata = metadata.clone();
-        metadata.mix(&"lib");
         let mut target = Target::lib_target(&l.name(), crate_types,
-                                            &path.to_path(),
-                                            metadata);
+                                            &path.to_path());
         configure(l, &mut target);
         dst.push(target);
     }
@@ -1113,8 +1101,7 @@ fn normalize(lib: &Option<TomlLibTarget>,
             let path = bin.path.clone().unwrap_or_else(|| {
                 PathValue::Path(default(bin))
             });
-            let mut target = Target::bin_target(&bin.name(), &path.to_path(),
-                                                None);
+            let mut target = Target::bin_target(&bin.name(), &path.to_path());
             configure(bin, &mut target);
             dst.push(target);
         }
@@ -1124,7 +1111,7 @@ fn normalize(lib: &Option<TomlLibTarget>,
         let name = format!("build-script-{}",
                            cmd.file_stem().and_then(|s| s.to_str()).unwrap_or(""));
 
-        dst.push(Target::custom_build_target(&name, cmd, None));
+        dst.push(Target::custom_build_target(&name, cmd));
     }
 
     fn example_targets(dst: &mut Vec<Target>,
@@ -1141,40 +1128,29 @@ fn normalize(lib: &Option<TomlLibTarget>,
         }
     }
 
-    fn test_targets(dst: &mut Vec<Target>, tests: &[TomlTestTarget],
-                    metadata: &Metadata,
+    fn test_targets(dst: &mut Vec<Target>,
+                    tests: &[TomlTestTarget],
                     default: &mut FnMut(&TomlTestTarget) -> PathBuf) {
         for test in tests.iter() {
             let path = test.path.clone().unwrap_or_else(|| {
                 PathValue::Path(default(test))
             });
 
-            // make sure this metadata is different from any same-named libs.
-            let mut metadata = metadata.clone();
-            metadata.mix(&format!("test-{}", test.name()));
-
-            let mut target = Target::test_target(&test.name(), &path.to_path(),
-                                                 metadata);
+            let mut target = Target::test_target(&test.name(), &path.to_path());
             configure(test, &mut target);
             dst.push(target);
         }
     }
 
-    fn bench_targets(dst: &mut Vec<Target>, benches: &[TomlBenchTarget],
-                     metadata: &Metadata,
+    fn bench_targets(dst: &mut Vec<Target>,
+                     benches: &[TomlBenchTarget],
                      default: &mut FnMut(&TomlBenchTarget) -> PathBuf) {
         for bench in benches.iter() {
             let path = bench.path.clone().unwrap_or_else(|| {
                 PathValue::Path(default(bench))
             });
 
-            // make sure this metadata is different from any same-named libs.
-            let mut metadata = metadata.clone();
-            metadata.mix(&format!("bench-{}", bench.name()));
-
-            let mut target = Target::bench_target(&bench.name(),
-                                                  &path.to_path(),
-                                                  metadata);
+            let mut target = Target::bench_target(&bench.name(), &path.to_path());
             configure(bench, &mut target);
             dst.push(target);
         }
@@ -1183,7 +1159,7 @@ fn normalize(lib: &Option<TomlLibTarget>,
     let mut ret = Vec::new();
 
     if let Some(ref lib) = *lib {
-        lib_target(&mut ret, lib, metadata);
+        lib_target(&mut ret, lib);
         bin_targets(&mut ret, bins,
                     &mut |bin| Path::new("src").join("bin")
                                    .join(&format!("{}.rs", bin.name())));
@@ -1201,7 +1177,7 @@ fn normalize(lib: &Option<TomlLibTarget>,
                     &mut |ex| Path::new("examples")
                                    .join(&format!("{}.rs", ex.name())));
 
-    test_targets(&mut ret, tests, metadata, &mut |test| {
+    test_targets(&mut ret, tests, &mut |test| {
         if test.name() == "test" {
             Path::new("src").join("test.rs")
         } else {
@@ -1209,7 +1185,7 @@ fn normalize(lib: &Option<TomlLibTarget>,
         }
     });
 
-    bench_targets(&mut ret, benches, metadata, &mut |bench| {
+    bench_targets(&mut ret, benches, &mut |bench| {
         if bench.name() == "bench" {
             Path::new("src").join("bench.rs")
         } else {